
'use strict';
/**
 * Cross Domain JSONP[Get]
 * 
 * @param {string} url 请求地址
 * @param {object} options 请求的配置项
 * @param {number} options.timeout 请求的超时时间
 * @param {string} options.charset 请求使用的字符集
 * @param {string} options.callback 与被请求地址约定的callback名称 
 */
function jsonp(url, options) {
    var basicSetup = JSONP.basicSetup;
    var timeout = 'number' === typeof options.timeout && !isNaN(options.timeout) ? options.timeout : basicSetup.timeout;
    var charset = 'string' === typeof options.charset ? options.charset : basicSetup.charset;
    var callback = 'string' === typeof options.callback ? options.callback : basicSetup.callback;
    var ID = Date.now() + '_' + Math.floor(Math.random() * 100000);
    var timer;

    function destroy() {
        var script = document.getElementById(ID);
        if (script) {
            document.getElementsByTagName('head')[0].removeChild(script);
        }
        if (timer) {
            clearTimeout(timer);
        };
        try {
            delete window[ID];
        } catch (e) {
            window[ID] = undefined;
        }
    }

    return new Promise(function (resolve, reject) {
        window[ID] = function (response) {
            resolve({
                status: 0,
                dataset: response
            });
            destroy();
        };

        url += (url.indexOf('?') === -1) ? '?' : '&';

        var script = document.createElement('script');

        script.setAttribute('src', `${url}${callback}=${ID}`);
        if (charset) {
            script.setAttribute('charset', charset);
        }
        script.id = ID;
        document.getElementsByTagName('head')[0].appendChild(script);

        timer = setTimeout(function () {
            reject({
                status: 10003, // JSONP请求超时
                dataset: null
            });
            destroy();
        }, timeout);

        script.onerror = function () {
            reject({
                status: 10004, // 请求出错 
                dataset: null
            });
            destroy();
        };
    });
}

export class JSONP {

    /**
     * JSONP Get 
     * @param {string} url 请求的地址
     * @param {object} options 请求的配置项
     * @param {function} options.start 请求开始之前执行的函数
     * @param {function} options.finsh 请求完成以后执行的函数
     * @param {function} options.success 请求成功之后公用的数据集处理函数
     * @param {function} options.error 请求出错之后公用的处理函数
     * @param {object} options.status 请求中使用的状态码
     * @param {object} options 请求的配置项
     */
    async jsonp(url, options) {
        if ('string' !== typeof url) {
            throw new Error('[Jsonp Error] `url` must be a string !');
        }
        !jsonp.configurable ? this.configure() : jsonp.configurable = 1;
        options = 'object' !== typeof options ? {} : options;

        var basicSetup = JSONP.basicSetup;
        var start = 'function' === typeof options.start ? options.start : basicSetup.start;
        var finsh = 'function' === typeof options.finsh ? options.finsh : basicSetup.finsh;
        var success = 'function' === typeof options.success ? options.success : basicSetup.success;
        var error = 'function' === typeof options.error ? options.error : basicSetup.error;
        var status = Object.assign({}, basicSetup.status, options.status);
        var dataset;

        start();
        var dataset = await jsonp(url, options).then(function (res) {
            if (res.status === 0) {
                return success(res.dataset);
            }
            return null;
        }).catch(function (err) {
            error(new Error('[JSONP Error] ' + status[res.status] + '，请求地址 ' + url));
            return null;
        });
        finsh();

        return dataset;
    }

    /**
     * JSONP 全局配置 
     * @param {object} options
     **/
    configure(options) {
        options = 'object' !== typeof options ? {} : options;
        var noop = function () { };
        var returned = function (res) { return res };
        var basicSetup = JSONP.basicSetup;

        basicSetup.start = 'function' === typeof options.start ? options.start : noop;
        basicSetup.finsh = 'function' === typeof options.finsh ? options.finsh : noop;
        basicSetup.success = 'function' === typeof options.success ? options.success : returned;
        basicSetup.error = 'function' === typeof options.error ? options.error : noop;
        basicSetup.callback = options.callback ? options.callback : 'callback';
        basicSetup.timeout = 'number' === typeof options.timeout && !isNaN(options.timeout) ? options.timeout : 5000;
        basicSetup.charset = 'string' === typeof options.charset ? options.charset : 'utf-8';
        basicSetup.status = Object.assign({}, basicSetup.status, options.status);
    }
};

// 全局基础配置
JSONP.basicSetup = {
    start: null,     // loading开始函数 
    finsh: null,     // loading结束函数 
    callback: null,  // 回调函数名称，与后端约定的名称
    success: null,   // 公用的请求成功之后的处理函数
    error: null,     // 公用的请求出错之后的处理函数
    timeout: null,   // 请求超时时间
    charset: null,   // 请求使用的字符集
    status: {        // 错误编码
        10003: 'JSONP请求超时',
        10004: 'JSONP请求出错，可能是网络问题！'
    }
}; 